<template>
  <div v-loading="queueLoading" class="container">
    <div class="header">
      <div class="title">{{ $t("staff_list.contract_info") }}</div>
      <el-button
        v-auth="{ authArr: auth, key: 'edit' }"
        type="primary"
        :disabled="state.plusDisabled"
        :icon="CirclePlus"
        link
        @click="handlePlus()"
      >
        {{ $t("staff_list.add_contract") }}
      </el-button>
    </div>
    <div class="body">
      <div class="merak-overflow-y">
        <div v-for="(form, index) in formList" class="form-wrapper">
          <div class="form-header">
            <div class="form-title">
              <template v-if="!!form.value.user_contract_id">{{ form.value.contract_type_txt }}</template>
            </div>
            <div class="form-body">
              <div v-if="!!form.editor" class="form-btns">
                <el-button @click="handleCancel(index)">{{ $t("merak.cancel") }}</el-button>
                <el-button type="primary" @click="handleSave(form)">{{ $t("merak.save") }}</el-button>
              </div>
              <el-dropdown
                v-else-if="!!form.value.user_contract_id"
                trigger="click"
                @visible-change="open => (form.dropdownOpen = open)"
                @command="command => handleCommand(command, form)"
              >
                <el-button
                  v-auth="{ authArr: auth, key: 'edit' }"
                  :disabled="state.plusDisabled"
                  :icon="DropdownIcon(!!form.dropdownOpen)"
                >
                  {{ $t("merak.action") }}
                </el-button>
                <template #dropdown>
                  <el-dropdown-menu>
                    <el-dropdown-item command="editor">{{ $t("merak.edit") }}</el-dropdown-item>
                    <el-dropdown-item command="renewal">{{ $t("staff_list.renewal_contract") }}</el-dropdown-item>
                    <el-dropdown-item command="secure">{{ $t("staff_list.secure_contract") }}</el-dropdown-item>
                    <el-dropdown-item command="delete">{{ $t("merak.delete") }}</el-dropdown-item>
                  </el-dropdown-menu>
                </template>
              </el-dropdown>
            </div>
          </div>
          <el-form
            :ref="el => (form.ref = el as FormInstance)"
            labelWidth="auto"
            :labelPosition="!!form.editor ? 'top' : 'right'"
            :model="form.value"
            :hideRequiredAsterisk="!form.editor"
            :rules="formRules"
          >
            <el-row :gutter="40">
              <template v-for="item in [...contractItems]">
                <el-col
                  v-if="['contract_period', 'contract_end'].includes(item.prop) ? form.value.contract_type !== 3 : true"
                  :span="8"
                >
                  <MerakXFormItem
                    v-bind="item"
                    :label="$t(`staff_list.${item.prop}`)"
                    :rules="contractEndRules(item.prop, form.value)"
                    :readonly="!form.editor"
                    :queryOptions="field => queryOptions(field)"
                    v-model:value="form.value[item.prop]"
                    v-model:default="form.value[`${item.prop}_txt`]"
                    @change="params => handleFormItemChange(params, form)"
                  />
                </el-col>
              </template>
            </el-row>
          </el-form>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="tsx">
import { getCurrentInstance, inject, reactive, onMounted } from "vue";

import { useRoute } from "vue-router";

import useLoading from "@/hooks/useLoading";

import useDateFormat from "@/hooks/useDateFormat";

import {
  FormInstance,
  FormRules,
  FormItemRule,
  ElMessage,
  ElButton,
  ElDropdown,
  ElDropdownMenu,
  ElDropdownItem,
  ElForm,
  ElRow,
  ElCol
} from "element-plus";
import { CirclePlus } from '@element-plus/icons-vue';

import MerakIcon from "@/components/MerakIcon/index.vue";
import MerakXFormItem, { MerakXFormItemChangeParams } from "@/components/MerakXFormItem";

import { contractItems } from "../formItems";

import { ResultEnum } from "@/enums/httpEnum";
import {
  getDictOptions,
  getPersonnelContract,
  savePersonnelContract,
  securePersonnelInfo,
  deletePersonnelInfo
} from "@/api/modules/sysManage/personnel";

import { confirmWarningMsg } from "@/utils/messageUtils";

import dayjs from "dayjs";

type FormType = {
  ref?: FormInstance;
  value: Record<string, any>;
  editor?: boolean;
  dropdownOpen?: boolean;
};

const PlusIcon = (
  <MerakIcon size="14">
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
      <path d="M17,13H13V17H11V13H7V11H11V7H13V11H17M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2Z" />
    </svg>
  </MerakIcon>
);

const DropdownIcon = (open: boolean = false) => (
  <MerakIcon size="16">
    {open ? (
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
        <path d="M7,15L12,10L17,15H7Z" />
      </svg>
    ) : (
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
        <path d="M7,10L12,15L17,10H7Z" />
      </svg>
    )}
  </MerakIcon>
);

const currentInstance = getCurrentInstance();

const route = useRoute();

const { queueId, queueLoading } = useLoading();

const { format } = useDateFormat();

const auth = inject("auth");

const state = reactive<{
  plusDisabled: boolean;
  copyValue: Record<string, any>;
}>({
  plusDisabled: false,
  copyValue: {}
});

const formRules = reactive<FormRules>({
  contract_company_id: [{ required: true, message: currentInstance?.proxy?.$t("staff_list.contract_company_id") }],
  contract_type: [{ required: true, message: currentInstance?.proxy?.$t("staff_list.contract_type") }],
  contract_period: [
    {
      required: true,
      trigger: "change",
      validator: (rule, value, callback) => {
        const reg = /^\d+(\.\d{1,1})?$/;
        if (!!value && reg.test(value)) {
          if (Math.floor(value) > 100) {
            callback(new Error(currentInstance?.proxy?.$t("staff_list.contract_period_valid_limit")));
          } else {
            callback();
          }
        } else {
          callback(new Error(currentInstance?.proxy?.$t("staff_list.one_float_valid")));
        }
      }
    }
  ],
  contract_status: [{ required: true, message: currentInstance?.proxy?.$t("staff_list.contract_status") }],
  contract_start: [{ required: true, message: currentInstance?.proxy?.$t("staff_list.contract_start") }],
  contract_date: [{ required: true, message: currentInstance?.proxy?.$t("staff_list.contract_date") }]
});

const formList = reactive<FormType[]>([]);

const contractEndRules: (prop: string, formValue: Record<string, any>) => FormItemRule[] | undefined = (prop, formValue) => {
  if (prop === "contract_end" && formValue.contract_type !== 3) {
    return [{ required: true, message: currentInstance?.proxy?.$t("staff_list.contract_end") }];
  }
  return;
};

const handlePlus = (formValue?: Record<string, any>) => {
  const value: Record<string, any> = {};
  if (!!formValue) {
    if (
      (typeof formValue.contract_company_id === "number" || !!formValue.contract_company_id) &&
      !!formValue.contract_company_id_txt
    ) {
      value.contract_company_id = formValue.contract_company_id;
      value.contract_company_id_txt = formValue.contract_company_id_txt;
    }
    if ((typeof formValue.contract_type === "number" || !!formValue.contract_type) && !!formValue.contract_type_txt) {
      value.contract_type = formValue.contract_type;
      value.contract_type_txt = formValue.contract_type_txt;
    }
    if ((typeof formValue.contract_period === "number" || !!formValue.contract_period) && formValue.contract_type !== 3) {
      value.contract_period = formValue.contract_period;
    }
    if (!!formValue.contract_end) {
      value.contract_start = dayjs(formValue.contract_end).add(1, "day").format(format);
    }
    if ((typeof value.contract_period === "number" || !!value.contract_period) && value.contract_start) {
      value.contract_end = dayjs(value.contract_start)
        .add(365 * Number(value.contract_period), "day")
        .format(format);
    }
  }
  state.plusDisabled = true;
  formList.unshift({ value, editor: true });
};

const handleCancel = (index: number) => {
  const form = formList[index];
  state.plusDisabled = false;
  form.ref?.clearValidate();
  if (!!form.value.user_contract_id) {
    for (let key of Object.keys(state.copyValue)) {
      form.value[key] = state.copyValue[key];
    }
    form.editor = false;
  } else {
    formList.splice(index, 1);
  }
};

const handleSave = (form: FormType) => {
  form.ref?.validate().then(() => {
    confirmWarningMsg({
      msg: currentInstance?.proxy?.$t("staff_list.save_contract_warning") ?? "",
      callback: (status: string) => {
        if (status === "confirm") {
          const { id } = route.query;
          const params: Record<string, any> = { user_id: id };
          for (let key of Object.keys(form.value)) {
            if (key.includes("_txt")) continue;
            params[key] = form.value[key];
          }
          savePersonnelContract(params).then(({ code, data, message }) => {
            if (code == ResultEnum.SUCCESS) {
              form.editor = false;
              state.plusDisabled = false;
              if (!!form.value.user_contract_id) {
                ElMessage.success(currentInstance?.proxy?.$t("staff_list.edit_contract_success"));
              } else {
                form.value.user_contract_id = data;
                ElMessage.success(currentInstance?.proxy?.$t("staff_list.add_contract_success"));
              }
              if (form.value.contract_status === 1) {
                formList.forEach(formOption => {
                  if (formOption.value.contract_status === 1 && formOption.value.user_contract_id !== data) {
                    formOption.value.contract_status = -1;
                    formOption.value.contract_status_txt = currentInstance?.proxy?.$t("staff_list.contract_status_secure");
                  }
                });
              }
            } else if (typeof message === "string") {
              ElMessage.error(message);
            } else {
              const msg = Object.values(message)?.[0];
              ElMessage.error(msg);
            }
          });
        }
      }
    });
  });
};

const handleCommand = (command: string, form: FormType) => {
  const id = form.value.user_contract_id;
  form.dropdownOpen = false;
  switch (command) {
    case "editor":
      for (let key of Object.keys(form.value)) {
        state.copyValue[key] = form.value[key];
      }
      form.editor = true;
      state.plusDisabled = true;
      break;
    case "renewal":
      handlePlus(form.value);
      break;
    case "secure":
      confirmWarningMsg({
        msg: currentInstance?.proxy?.$t("staff_list.secure_contract_warning") ?? "",
        callback: (status: string) => {
          if (status === "confirm") {
            securePersonnelInfo(id).then(({ code, message }) => {
              if (code == ResultEnum.SUCCESS) {
                form.value.contract_status = -1;
                form.value.contract_status_txt = currentInstance?.proxy?.$t("staff_list.contract_status_secure");
                ElMessage.success(currentInstance?.proxy?.$t("staff_list.secure_contract_success"));
              } else if (typeof message === "string") {
                ElMessage.error(message);
              } else {
                const msg = Object.values(message)?.[0];
                ElMessage.error(msg);
              }
            });
          }
        }
      });
      break;
    case "delete":
      confirmWarningMsg({
        msg: currentInstance?.proxy?.$t("staff_list.delete_contract_warning") ?? "",
        callback: (status: string) => {
          if (status === "confirm") {
            deletePersonnelInfo(id).then(({ code, message }) => {
              if (code == ResultEnum.SUCCESS) {
                const index = formList.findIndex(formOption => formOption.value.user_contract_id === id);
                if (index !== -1) {
                  formList.splice(index, 1);
                }
                ElMessage.success(currentInstance?.proxy?.$t("staff_list.delete_contract_success"));
              } else if (typeof message === "string") {
                ElMessage.error(message);
              } else {
                const msg = Object.values(message)?.[0];
                ElMessage.error(msg);
              }
            });
          }
        }
      });
      break;
    default:
      break;
  }
};

const handleFormItemChange = (params: MerakXFormItemChangeParams, form: FormType) => {
  switch (params.type) {
    case "input":
      if (!!params.data) {
        form.value[params.prop] = params.data.trim();
      }
      if (params.prop === "contract_period" && !!form.value.contract_start) {
        form.value.contract_end = dayjs(form.value.contract_start)
          .add(365 * Number(params.data), "day")
          .format(format);
      }
      break;
    case "select":
      if (!!params.data?.label) {
        form.value[`${params.prop}_txt`] = params.data?.label;
      }
      if (params.prop === "contract_type" && params.data.value === 3) {
        if (!!form.value.contract_start) {
          form.value.contract_end = dayjs(form.value.contract_start).add(100, "year").format(format);
        }
        delete form.value.contract_period;
      }
      break;
    case "datePicker":
      if (params.prop === "contract_start") {
        if (form.value.contract_type === 3) {
          form.value.contract_end = dayjs(params.data).add(100, "year").format(format);
        } else if (typeof form.value.contract_period === "number" || !!form.value.contract_period) {
          form.value.contract_end = dayjs(params.data)
            .add(365 * Number(form.value.contract_period), "day")
            .format(format);
        }
      }
      break;
    default:
      break;
  }
};

const queryOptions = async (key?: string) => {
  if (!key) return;
  return getDictOptions({ key }).then(({ code, data }) => {
    if (code == ResultEnum.SUCCESS) {
      return [...data].map(item => ({ value: item.key, label: item.value }));
    }
    return;
  });
};

onMounted(() => {
  const { id } = route.query;
  if (!!id) {
    getPersonnelContract(id as string, queueId.value).then(({ code, data }) => {
      if (code == ResultEnum.SUCCESS) {
        for (let item of data) {
          formList.push({ value: { ...item } });
        }
      }
    });
  }
});
</script>

<style scoped lang="scss">
.container {
  display: flex;
  flex-direction: column;
  height: 100%;
  .header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: var(--merak-padding);
    height: var(--merak-button-size);
    font-size: 16px;
    .el-button {
      padding: 0;
      min-width: auto;
    }
  }
  .body {
    flex: auto;
    min-height: 0;
    .form-wrapper {
      & + .form-wrapper {
        margin-top: var(--merak-padding);
      }
      .form-header {
        display: flex;
        align-items: center;
        justify-content: space-between;
        margin-bottom: var(--merak-space);
      }
      .el-form.el-form--label-right {
        :deep(.el-form-item__label-wrap) {
          margin-right: 30px;
        }
      }
    }
  }
}
</style>
